home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************
- * file: DIALOG.C
- * purpose:
- * dialog box functions for simple gui
- * for now all dialog boxes are modal
- * contains:
- * dialog_open(DIALOG_ITEM dialog[],short number_of_items,short loc_x,short loc_y,short width,short height); draws a dialog box
- * dialog_message_handler(MESSAGE *message,DIALOG_ITEM *dialog); handles dialog box messages
- * dialog_close(DIALOG_ITEM dialog[]); erases a dialog box
- * dialog_add_item(short type,void *data,DIALOG_ITEM dialog[]); add an item to an open dialog
- * editbox_initialize(EDITBOX *edit); initialize an editbox with a new string
- * listbox_initialize(LISTBOX *list); initialize a listbox with a new list
- * radiobutton_set(RADIOBUTTON *radio,short id); sets a particular radiobutton
- * checkbox_set(BUTTON *button,short id); sets a checkbox
- * checkbox_clear(BUTTON *button,short id); clears a checkbox
- * system: Written for the flash graphics library in Zortech 3.0
- * copyright: 1992 by David Weber. All rights reserved.
- * This software can be used for any purpose as object, library or executable.
- * It cannot be sold for profit as source code.
- * history:
- * 01-01-92 - initial code
- * 01-31-93 - this code is now obsolete, see the CPP gui package
- **************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "gui.h"
-
- /* local defines */
- #define FOCUS_CLEAR 0
- #define FOCUS_SET 1
-
- /* local prototypes */
- static void dialog_focus_draw(DIALOG_ITEM *dialog,short type);
- static short dialog_refocus(DIALOG_ITEM dialog[],DIALOG_ITEM *item);
- static void dialog_focus_next(DIALOG_ITEM dialog[]);
- static void dialog_focus_previous(DIALOG_ITEM dialog[]);
- static short text_open(short x,short y,TEXT *text,fg_pbox_t area,DIALOG_ITEM *d);
- static short dialog_draw_text(short x,short y,char *str,fg_pbox_t clip);
- static short dialog_draw_gray_text(short x,short y,char *str,fg_pbox_t clip);
- static short button_open(short x,short y,BUTTON *button,fg_pbox_t area,DIALOG_ITEM *d);
- static short checkbox_open(short x,short y,BUTTON *button,fg_pbox_t area,DIALOG_ITEM *d);
- static void checkbox_draw(short x,short y,BUTTON *b,fg_pbox_t clip,fg_pbox_t focus);
- static void checkbox_draw_gray(short x,short y,BUTTON *b,fg_pbox_t clip,fg_pbox_t focus);
- static void checkbox_mark(BUTTON *b);
- static void checkbox_unmark(BUTTON *b);
- static short radiobutton_open(short x,short y,RADIOBUTTON *radio,fg_pbox_t area,DIALOG_ITEM *d);
- static void radiobutton_mark(BUTTON *b,DIALOG_ITEM *d);
- static void radiobutton_unmark(BUTTON *b);
- static BUTTON *radiobutton_unmark_all(BUTTON *first,short number_of_buttons);
- static BUTTON *radiobutton_previous(BUTTON *first,short number_of_buttons);
- static BUTTON *radiobutton_next(BUTTON *first,short number_of_buttons);
- static short listbox_open(short x,short y,LISTBOX *list,fg_pbox_t area,DIALOG_ITEM *d);
- static void listbox_close(LISTBOX *list);
- static void listbox_free(LISTBOX *list);
- static void listbox_draw_contents(LISTBOX *list);
- static short listbox_allocate_page(LISTBOX *list,short type);
- static void listbox_mark(LISTBOX *list);
- static short listbox_scroll(LISTBOX *list,short number_of_lines);
- static char *listbox_current_data(LISTBOX *list,short offset);
- static short editbox_open(short x,short y,EDITBOX *edit,fg_pbox_t area,DIALOG_ITEM *d);
- static void editbox_close(EDITBOX *edit);
- static void editbox_draw(EDITBOX *edit);
- static void editbox_cursor(EDITBOX *edit);
- static short editbox_edit(EDITBOX *edit,short key);
-
-
- /************************************************
- * function: short dialog_open(DIALOG_ITEM dialog[],short number_of_items,short loc_x,short loc_y,short width,short height)
- * registers a dialog box, initializes all the hotspots and draws it
- * In this simple gui dialog boxes are always modal
- * parameters: array of dialog items in dialog box, number of items in array,
- * location of box relative to lower left corner of screen in quarter text
- * cell units, width and height of box also in quarter text cell units.
- * If loc_x or loc_y is -1 then the box is centered in the screen
- * returns: 1 if opened or 0 if failed because of lack of resources
- ************************************************/
- short dialog_open(DIALOG_ITEM dialog[],short number_of_items,short loc_x,short loc_y,short width,short height)
- {
- short i,j,fail;
- DIALOG_ITEM *d,*d2;
- fg_box_t dialog_area;
- MESSAGE error;
-
- i = 0; /* verify parameters */
- if (number_of_items < 0 || number_of_items > DIALOG_MAX_ITEMS)
- i = 1;
- else
- for (j = 0 ; j < number_of_items ; j++)
- {
- d = &dialog[j];
- if (d->type < DIALOG_MIN_TYPE || d->type > DIALOG_MAX_TYPE || d->data == NULL)
- i = 1;
- }
- if (i)
- {
- error.id = gui_errno = M_INVALID_PARMS;
- error.data.ptr_data = dialog_open;
- message_send(&error);
- return 0;
- }
- fg_msm_hidecursor();
- loc_x = (gui_char_width * loc_x) / DIALOG_UNITS; /* screen units */
- loc_y = (gui_char_height * loc_y) / DIALOG_UNITS;
- width = (gui_char_width * width) / DIALOG_UNITS;
- height = (gui_char_height * height) / DIALOG_UNITS;
- if (loc_x < 0 || loc_y < 0) /* center it? */
- {
- loc_x = (fg.displaybox[FG_X2] - fg.displaybox[FG_X1])/2 - width/2;
- if (loc_x < 0) loc_x = 0;
- loc_y = (fg.displaybox[FG_Y2] - fg.displaybox[FG_Y1])/2 - height/2;
- if (loc_y < 0) loc_y = 0;
- }
- loc_x += fg.displaybox[FG_X1];
- loc_y += fg.displaybox[FG_Y1];
- if (loc_x + width > fg.displaybox[FG_X2]) /* adjust box to fit screen */
- {
- loc_x = fg.displaybox[FG_X2] - width;
- if (loc_x < 0)
- loc_x = 0;
- }
- if (loc_y + height > fg.displaybox[FG_Y2])
- {
- loc_y = fg.displaybox[FG_Y2] - height;
- if (loc_y < 0)
- loc_y = 0;
- }
- dialog_area[FG_X1] = loc_x; /* coordinates of dialog box */
- dialog_area[FG_X2] = loc_x + width;
- dialog_area[FG_Y1] = loc_y;
- dialog_area[FG_Y2] = loc_y + height;
- fg_boxclip(fg.displaybox,dialog_area,dialog_area);
- if (!object_add(OBJECT_DIALOG,(GENERIC_MESSAGE_HANDLER)dialog_message_handler,dialog,dialog_area))
- { /* add object to active list */
- fg_msm_showcursor();
- fg_flush();
- return 0;
- }
- fg_fillbox(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,dialog_area); /* draw box */
- fg_drawbox(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,dialog_area,fg.displaybox);
- for (i=0, d2=NULL, fail=0 ; i < number_of_items ; i++)
- {
- d = &dialog[i];
- d->dialog_state = DIALOG_FIXED;
- switch (d->type) /* set up hotspots and draw items */
- {
- case DIALOG_TEXT:
- fail = text_open(loc_x,loc_y,(TEXT *)d->data,dialog_area,d);
- break;
- case DIALOG_BUTTON:
- fail = button_open(loc_x,loc_y,(BUTTON *)d->data,dialog_area,d);
- break;
- case DIALOG_CHECKBOX:
- fail = checkbox_open(loc_x,loc_y,(BUTTON *)d->data,dialog_area,d);
- break;
- case DIALOG_RADIOBUTTON:
- fail = radiobutton_open(loc_x,loc_y,(RADIOBUTTON *)d->data,dialog_area,d);
- break;
- case DIALOG_LISTBOX:
- fail = listbox_open(loc_x,loc_y,(LISTBOX *)d->data,dialog_area,d);
- break;
- case DIALOG_EDITBOX:
- fail = editbox_open(loc_x,loc_y,(EDITBOX *)d->data,dialog_area,d);
- break;
- default:
- break;
- }
- d->next = NULL; /* thread linked list */
- if (d2 != NULL)
- d2->next = d;
- d2 = d;
- if (fail) /* handle errors */
- {
- if (fail != M_NULL_ERROR) /* null error means error message was already sent */
- {
- error.id = gui_errno = fail;
- error.data.ptr_data = dialog_open;
- message_send(&error);
- }
- dialog_close(dialog);
- fg_msm_showcursor();
- fg_flush();
- return 0;
- }
- }
- exclusive_focus_set(dialog); /* force exclusive focus on dialog box */
- d->dialog_state |= DIALOG_FOCUS_HERE; /* local focus on first dialog item */
- dialog_focus_next(dialog);
- fg_msm_showcursor();
- fg_flush();
- return 1;
- }
-
-
- /************************************************
- * function: void dialog_message_handler(MESSAGE *message,DIALOG_ITEM *dialog)
- * handles messages for dialog boxes, the following transforms occur:
- * BUTTON - when selected the button id is returned as a message id
- * CHECKBOX - when selected the checkbox id is returned as a message id,
- * message->data.short_data.x is 1 if box is on or 0 if off
- * RADIOBUTTON - when any button in the radio button set is selected the
- * radio set id is returned as the message id, the id of the
- * button in the set which was selected is returned as
- * message->data.short_data.x and the button which was deselected
- * is returned as message->data.short_data.y
- * LISTBOX - when any item displayed in a list box is selected with either
- * the mouse or with the RETURN key, the listbox id is
- * returned as the message id and a pointer to the string is
- * returned as message->data.ptr_data
- * EDITBOX - If the RETURN key is hit while the editbox has the focus, the
- * editbox id is returned as the message id and
- * message->data.short_data.x is EDITBOX_ACCEPT. If a change
- * is made to the contents of an editbox, the editbox id is
- * returned as the message id and message->data.short_data.x
- * is EDITBOX_CHANGE
- * parameters: pointer to message, pointer to object data
- * returns: nothing
- ************************************************/
- void dialog_message_handler(MESSAGE *message,DIALOG_ITEM *dialog)
- {
- DIALOG_ITEM *d;
- BUTTON *b,*b2;
- RADIOBUTTON *r;
- LISTBOX *l;
- EDITBOX *e;
- char *p;
- short i,key,x,y,focus;
-
- switch (message->id)
- {
- case M_KEY: /*** KEY MESSAGE ***/
- key = message->data.short_data.x;
- if (key == TAB) /* focus on next */
- {
- dialog_focus_next(dialog);
- message->id = M_NONE;
- return;
- }
- if (key == SHIFTTAB) /* focus on previous */
- {
- dialog_focus_previous(dialog);
- message->id = M_NONE;
- return;
- }
- for (d = dialog ; d != NULL ; d = d->next)
- {
- if (d->dialog_state & DIALOG_FOCUS_HERE) /* does this one have the focus? */
- focus = 1;
- else
- focus = 0;
- switch (d->type)
- {
- case DIALOG_CHECKBOX:
- b = (BUTTON *) d->data;
- if (is_active(*b))
- if (b->accelerator == key || ((key == RETURN || key == SPACE) && focus))
- {
- if (is_selected(*b))
- {
- checkbox_unmark(b);
- message->data.short_data.x = 0;
- }
- else
- {
- checkbox_mark(b);
- message->data.short_data.x = 1;
- }
- dialog_refocus(dialog,d);
- message->id = b->id;
- return;
- }
- break;
- case DIALOG_BUTTON:
- b = (BUTTON *) d->data;
- if (is_active(*b))
- if (b->accelerator == key || (key == RETURN && focus))
- {
- dialog_refocus(dialog,d);
- message->id = b->id;
- return;
- }
- break;
- case DIALOG_RADIOBUTTON:
- r = (RADIOBUTTON *) d->data;
- if (is_active(*r))
- {
- for (i = 0, b = r->buttons ; i < r->number_of_buttons ; i++, b++)
- if (is_active(*b))
- if (b->accelerator == key || ((key == RETURN || key == SPACE || key == DOWNARROW || key == UPARROW || key == RIGHTARROW || key == LEFTARROW) && focus))
- {
- if (b->accelerator != key)
- {
- if (key == UPARROW || key == LEFTARROW)
- b = radiobutton_previous(r->buttons,r->number_of_buttons);
- else
- b = radiobutton_next(r->buttons,r->number_of_buttons);
- }
- b2 = radiobutton_unmark_all(r->buttons,r->number_of_buttons);
- dialog_refocus(dialog,d);
- if (b2 == NULL)
- message->data.short_data.y = 0;
- else
- message->data.short_data.y = b2->id;
- message->data.short_data.x = b->id;
- radiobutton_mark(b,d);
- message->id = r->id;
- return;
- }
- }
- break;
- case DIALOG_LISTBOX:
- l = (LISTBOX *) d->data;
- if (is_active(*l) && focus)
- {
- i = 0;
- if (key == UPARROW) i = -1;
- if (key == DOWNARROW) i = 1;
- if (key == PGUP) i = -l->height/DIALOG_UNITS;
- if (key == PGDN) i = l->height/DIALOG_UNITS;
- if (key == CTRLPGUP || key == CTRLHOME) i = -10000;
- if (key == CTRLPGDN || key == CTRLEND) i = 10000;
- if (i)
- {
- listbox_scroll(l,i);
- message->id = M_NONE;
- return;
- }
- if (key == RETURN)
- {
- if ((p = listbox_current_data(l,l->screen_offset)) == NULL)
- break;
- message->id = l->id;
- message->data.ptr_data = p;
- return;
- }
- }
- break;
- case DIALOG_EDITBOX:
- e = (EDITBOX *) d->data;
- if (is_active(*e) && focus)
- {
- if (key == RETURN)
- {
- message->id = e->id;
- message->data.short_data.x = 1;
- return;
- }
- i = editbox_edit(e,key);
- if (i == 2)
- {
- message->id = e->id;
- message->data.short_data.x = 0;
- return;
- }
- if (i == 1)
- {
- message->id = M_NONE;
- return;
- }
- }
- break;
- default:
- break;
- }
- }
- break;
- case M_MOUSE_LEFT: /*** MOUSE MESSAGE ***/
- case M_MOUSE_CENTER:
- case M_MOUSE_RIGHT:
- x = message->data.short_data.x;
- y = message->data.short_data.y;
- for (d = dialog ; d != NULL ; d = d->next)
- {
- switch (d->type)
- {
- case DIALOG_BUTTON:
- case DIALOG_CHECKBOX:
- b = (BUTTON *) d->data;
- if (is_active(*b))
- {
- if (fg_pt_inbox(b->screen,x,y))
- { /* dialog item selected */
- dialog_refocus(dialog,d);
- if (d->type == DIALOG_CHECKBOX) /* mark or unmark checkbox */
- {
- if (is_selected(*b))
- {
- checkbox_unmark(b);
- message->data.short_data.x = 0;
- }
- else
- {
- checkbox_mark(b);
- message->data.short_data.x = 1;
- }
- }
- message->id = b->id;
- return;
- }
- }
- break;
- case DIALOG_RADIOBUTTON:
- r = (RADIOBUTTON *) d->data;
- if (is_active(*r))
- {
- for (i = 0, b = r->buttons ; i < r->number_of_buttons ; i++, b++)
- if (fg_pt_inbox(b->screen,x,y) && is_active(*b))
- {
- dialog_refocus(dialog,d);
- b2 = radiobutton_unmark_all(r->buttons,r->number_of_buttons);
- if (b2 == NULL)
- message->data.short_data.y = 0;
- else
- message->data.short_data.y = b2->id;
- message->data.short_data.x = b->id;
- radiobutton_mark(b,d);
- message->id = r->id;
- return;
- }
- }
- break;
- case DIALOG_LISTBOX:
- l = (LISTBOX *) d->data;
- if (is_active(*l))
- {
- if (fg_pt_inbox(l->screen,x,y))
- dialog_refocus(dialog,d);
- i = 0;
- if (fg_pt_inbox(l->up,x,y))
- i = -l->height/DIALOG_UNITS;
- if (fg_pt_inbox(l->down,x,y))
- i = l->height/DIALOG_UNITS;
- if (i)
- {
- listbox_scroll(l,i);
- message->id = M_NONE;
- return;
- }
- if (fg_pt_inbox(l->listbox,x,y))
- {
- i = (l->listbox[FG_Y2]-y)/gui_char_height;
- if ((p = listbox_current_data(l,i)) == NULL)
- break;
- l->screen_offset = i;
- listbox_mark(l);
- message->id = l->id;
- message->data.ptr_data = p;
- return;
- }
- if (fg_pt_inbox(l->marker,x,y))
- {
- i = (l->listbox[FG_Y2]-y)/gui_char_height;
- if ((p = listbox_current_data(l,i)) == NULL)
- break;
- l->screen_offset = i;
- listbox_mark(l);
- message->id = M_NONE;
- return;
- }
- }
- break;
- case DIALOG_EDITBOX:
- e = (EDITBOX *) d->data;
- if (is_active(*e))
- {
- if (fg_pt_inbox(e->screen,x,y))
- {
- dialog_refocus(dialog,d);
- i = (x - e->screen[FG_X1] - 1)/gui_char_width;
- if (i >= e->screen_width/DIALOG_UNITS)
- i = e->screen_width/DIALOG_UNITS - 1;
- e->xpos = e->scroll_offset + i;
- p = e->edit_string;
- i = e->xpos;
- if (i >= strlen(p))
- {
- memset(p+strlen(p),' ',i-strlen(p)+1);
- p[i+1] = 0;
- }
- editbox_cursor(e);
- message->id = M_NONE;
- return;
- }
- }
- break;
- default:
- break;
- }
- }
- break;
- default:
- return;
- }
- }
-
-
- /************************************************
- * function: short dialog_close(DIALOG_ITEM dialog[])
- * parameters: pointer to previously opened dialog box
- * returns: 1 if OK or 0 if failed
- ************************************************/
- short dialog_close(DIALOG_ITEM dialog[])
- {
- short ret;
- DIALOG_ITEM *d,*d2;
-
- fg_msm_hidecursor();
- exclusive_focus_clear(dialog); /* remove focus restriction */
- if ((ret = object_remove(dialog)) != 0)
- for (d = dialog ; d != NULL ; d = d2)
- {
- if (d->type == DIALOG_CHECKBOX)
- ((BUTTON *) d->data)->status &= ~DIALOG_OPENED;
- if (d->type == DIALOG_RADIOBUTTON)
- ((RADIOBUTTON *) d->data)->status &= ~DIALOG_OPENED;
- if (d->type == DIALOG_LISTBOX)
- listbox_close((LISTBOX *) d->data);
- if (d->type == DIALOG_EDITBOX)
- editbox_close((EDITBOX *) d->data);
- d2 = d->next;
- if (d->dialog_state == DIALOG_ALLOCATED)
- free(d);
- }
- fg_msm_showcursor();
- fg_flush();
- return ret;
- }
-
-
- /************************************************
- * function: short dialog_add_item(short type,void *data,DIALOG_ITEM dialog[])
- * parameters: type of item, item's data, opened dialog box
- * returns: 1 if added or 0 if failed
- ************************************************/
- short dialog_add_item(short type,void *data,DIALOG_ITEM dialog[])
- {
- short fail,x,y;
- GOB *o;
- DIALOG_ITEM *d,*d2;
- MESSAGE error;
-
- if (type < DIALOG_MIN_TYPE || type > DIALOG_MAX_TYPE || data == NULL)
- { /* is it proper? */
- error.id = gui_errno = M_INVALID_PARMS;
- error.data.ptr_data = dialog_add_item;
- message_send(&error);
- return 0;
- }
- if ((o = object_exists(dialog)) == NULL)
- { /* is it there? */
- error.id = gui_errno = M_NOT_OPEN;
- error.data.ptr_data = dialog_add_item;
- message_send(&error);
- return 0;
- }
- if ((d = (DIALOG_ITEM *) malloc(sizeof (DIALOG_ITEM))) == NULL)
- { /* are there resources? */
- error.id = gui_errno = M_NOMEM;
- error.data.ptr_data = dialog_add_item;
- message_send(&error);
- return 0;
- }
- d->dialog_state = DIALOG_ALLOCATED; /* build DIALOG_ITEM */
- d->type = type;
- d->data = data;
- d->next = NULL;
- fail = 0;
- x = o->screen[FG_X1];
- y = o->screen[FG_Y1];
- fg_msm_hidecursor();
- switch (type) /* set up hotspots and draw items */
- {
- case DIALOG_TEXT:
- fail = text_open(x,y,(TEXT *)data,o->screen,d);
- break;
- case DIALOG_BUTTON:
- fail = button_open(x,y,(BUTTON *)data,o->screen,d);
- break;
- case DIALOG_CHECKBOX:
- fail = checkbox_open(x,y,(BUTTON *)data,o->screen,d);
- break;
- case DIALOG_RADIOBUTTON:
- fail = radiobutton_open(x,y,(RADIOBUTTON *)data,o->screen,d);
- break;
- case DIALOG_LISTBOX:
- fail = listbox_open(x,y,(LISTBOX *)data,o->screen,d);
- break;
- case DIALOG_EDITBOX:
- fail = editbox_open(x,y,(EDITBOX *)data,o->screen,d);
- break;
- default:
- break;
- }
- fg_msm_showcursor();
- fg_flush();
- if (fail)
- { /* is it platable? */
- free(d);
- error.id = gui_errno = fail;
- error.data.ptr_data = dialog_add_item;
- message_send(&error);
- return 0;
- }
- for (d2 = dialog ; d2->next != NULL ; d2 = d2->next)
- ;
- /* thread it on the end */
- d2->next = d;
- return 1;
- }
-
-
- /************************************************
- * function: short editbox_initialize(EDITBOX *edit)
- * redraw the editbox with a new string, call this after you change the
- * string in the editbox structure
- * parameters: pointer to opened editbox
- * returns: 1 if OK or 0 if failed
- ************************************************/
- short editbox_initialize(EDITBOX *edit)
- {
- MESSAGE error;
-
- if ((edit->status & DIALOG_OPENED) == 0)
- { /* cannot initialize an unopened box */
- error.id = gui_errno = M_NOT_OPEN;
- error.data.ptr_data = editbox_initialize;
- message_send(&error);
- return 0;
- }
- edit->scroll_offset = edit->xpos = edit->insert = edit->curtype = edit->curpos = 0;
- editbox_draw(edit);
- return 1;
- }
-
-
- /************************************************
- * function: short listbox_initialize(LISTBOX *list)
- * clear listbox and redraw contents, call this if you change the
- * first_item next_item functions in the list data structure
- * parameters: pointer to listbox
- * returns: 1 if OK or 0 if failed
- ************************************************/
- short listbox_initialize(LISTBOX *list)
- {
- MESSAGE error;
-
- if ((list->status & DIALOG_OPENED) == 0)
- { /* cannot initialize an unopened box */
- error.id = gui_errno = M_NOT_OPEN;
- error.data.ptr_data = listbox_initialize;
- message_send(&error);
- return 0;
- }
- list->status &= ~DIALOG_COMPLETED;
- if (list->first_page != NULL) /* clean up old pages */
- listbox_free(list);
- if (!listbox_allocate_page(list,LISTBOX_FIRST_PAGE)) /* get first page */
- return 0;
- listbox_draw_contents(list); /* display it */
- listbox_mark(list); /* display marker */
- return 1;
- }
-
-
- /************************************************
- * function: short radiobutton_set(RADIOBUTTON *radio,short id)
- * set a button in a radiobutton set using the unique id associated with a
- * button to identify it.
- * parameters: radio button, unique id of button in radiobutton to set
- * returns: 1 if set or 0 if not
- ************************************************/
- short radiobutton_set(RADIOBUTTON *radio,short id)
- {
- BUTTON *old,*new,*b;
- short i;
-
- for (i = 0, b = radio->buttons, old = new = NULL ; i < radio->number_of_buttons ; i++, b++)
- {
- if (b->id == id)
- new = b;
- if (is_selected(*b))
- old = b;
- }
- if (new == NULL || is_inactive(*new))
- return 0;
- if (radio->status & DIALOG_OPENED)
- {
- radiobutton_unmark_all(radio->buttons,radio->number_of_buttons);
- radiobutton_mark(new,radio->dialog);
- }
- else
- {
- if (old != NULL)
- old->status &= ~DIALOG_SELECTED;
- new->status |= DIALOG_SELECTED;
- }
- return 1;
- }
-
-
- /************************************************
- * function: short checkbox_set(BUTTON *button,short id)
- * set a checkbox to on
- * parameters: checkbox button to set and the unique id of the button
- * returns: 1 if set or 0 if not
- ************************************************/
- short checkbox_set(BUTTON *button,short id)
- {
- if (button->id != id)
- return 0;
- if (button->status & DIALOG_OPENED)
- checkbox_mark(button);
- else
- button->status |= DIALOG_SELECTED;
- return 1;
- }
-
-
- /************************************************
- * function: short checkbox_clear(BUTTON *button,short id)
- * set a checkbox to off
- * parameters: checkbox button to clear and the unique id of the button
- * returns: 1 if set or 0 if not
- ************************************************/
- short checkbox_clear(BUTTON *button,short id)
- {
- if (button->id != id)
- return 0;
- if (button->status & DIALOG_OPENED)
- checkbox_unmark(button);
- else
- button->status &= ~DIALOG_SELECTED;
- return 1;
- }
-
-
- /* ---------------- LOCAL FUNCTIONS ---------------- */
-
- /* draw a dialog focus, type is FOCUS_CLEAR or FOCUS_SET */
- static void dialog_focus_draw(DIALOG_ITEM *dialog,short type)
- {
- short color1,color2;
- fg_box_t box;
-
- if (type == FOCUS_SET)
- color1 = color2 = COLOR_DIALOG_FOCUS;
- else
- {
- color1 = COLOR_DIALOG_FOREGROUND;
- color2 = COLOR_DIALOG_BACKGROUND;
- }
- fg_msm_hidecursor();
- fg_box_cpy(box,dialog->focus);
- fg_drawbox(color1,FG_MODE_SET,~0,FG_LINE_SOLID,box,fg.displaybox);
- box[FG_X1]--;
- box[FG_Y1]--;
- box[FG_X2]++;
- box[FG_Y2]++;
- fg_drawbox(color2,FG_MODE_SET,~0,FG_LINE_SOLID,box,fg.displaybox);
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* clear all dialog foci and refocus on item */
- static short dialog_refocus(DIALOG_ITEM dialog[],DIALOG_ITEM *item)
- {
- DIALOG_ITEM *d;
-
- if (item->dialog_state & DIALOG_FOCUS_SKIP) /* skip it? */
- return 0;
- for (d = dialog ; d != NULL ; d = d->next) /* clear all foci */
- if (d->dialog_state & DIALOG_FOCUS_HERE)
- {
- dialog_focus_draw(d,FOCUS_CLEAR);
- d->dialog_state &= ~DIALOG_FOCUS_HERE;
- }
- dialog_focus_draw(item,FOCUS_SET); /* set new focus */
- item->dialog_state |= DIALOG_FOCUS_HERE;
- return 1;
- }
-
-
- /* focus on the next dialog object */
- static void dialog_focus_next(DIALOG_ITEM dialog[])
- {
- DIALOG_ITEM *current,*mark;
-
- for (current = dialog ; current != NULL ; current = current->next)
- if (current->dialog_state & DIALOG_FOCUS_HERE) /* find focus */
- break;
- if (current == NULL)
- current = dialog;
- mark = current;
- do /* find next */
- {
- if (current->next == NULL)
- current = dialog;
- else
- current = current->next;
- if (current == mark)
- break;
- } while (current->dialog_state & DIALOG_FOCUS_SKIP);
- dialog_refocus(dialog,current);
- }
-
-
- /* focus on the previous dialog object */
- static void dialog_focus_previous(DIALOG_ITEM dialog[])
- {
- DIALOG_ITEM *d,*current,*mark;
-
- for (current = dialog ; current != NULL ; current = current->next)
- if (current->dialog_state & DIALOG_FOCUS_HERE) /* find focus */
- break;
- if (current == NULL)
- current = dialog;
- mark = current;
- do /* find previous */
- {
- for (d = dialog ; d->next != current && d->next != NULL ; d = d->next)
- ;
- current = d;
- if (current == mark)
- break;
- } while (current->dialog_state & DIALOG_FOCUS_SKIP);
- dialog_refocus(dialog,current);
- }
-
-
- /* ---------------- TEXT ---------------- */
-
- /* verify parameters and draw text, returns 0 if OK else returns error message */
- static short text_open(short x,short y,TEXT *text,fg_pbox_t area,DIALOG_ITEM *d)
- {
- if (text->loc_x < 0 || text->loc_y < 0 || text->name == NULL || (text->status & ~DIALOG_BITS))
- return M_INVALID_PARMS;
- d->focus[FG_X1] = x+(gui_char_width*text->loc_x)/DIALOG_UNITS;
- d->focus[FG_Y1] = y+(gui_char_height*text->loc_y)/DIALOG_UNITS;
- if (is_gray(*text))
- d->focus[FG_X2] = dialog_draw_gray_text(d->focus[FG_X1],d->focus[FG_Y1],text->name,area);
- if (is_active(*text))
- d->focus[FG_X2] = dialog_draw_text(d->focus[FG_X1],d->focus[FG_Y1],text->name,area);
- d->focus[FG_Y2] = d->focus[FG_Y1] + gui_char_height;
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- return 0;
- }
-
-
- /* draw dialog text str at coordinates x,y using '&' highlighting, return new x value */
- static short dialog_draw_text(short x,short y,char *str,fg_pbox_t clip)
- {
- short i,color;
-
- for (i = 0 ; str[i] != 0 ; i++)
- {
- color = COLOR_DIALOG_FOREGROUND;
- if (str[i] == '&')
- {
- i++;
- if (str[i] == 0)
- i--;
- if (str[i] != '&')
- color = COLOR_DIALOG_HIGHLIGHT;
- }
- fg_putc(color,FG_MODE_SET,~0,FG_ROT0,x,y,str[i],clip);
- x += gui_char_width;
- }
- return x;
- }
-
-
- /* draw gray dialog text str at coordinates x,y; return new x value */
- static short dialog_draw_gray_text(short x,short y,char *str,fg_pbox_t clip)
- {
- short i;
-
- for (i = 0 ; str[i] != 0 ; i++)
- {
- if (str[i] == '&')
- {
- i++;
- if (str[i] == 0)
- i--;
- }
- fg_putc(COLOR_DIALOG_GRAY,FG_MODE_SET,~0,FG_ROT0,x,y,str[i],clip);
- x += gui_char_width;
- }
- return x;
- }
-
-
- /* ---------------- BUTTON ---------------- */
-
- /* verify parameters and draw button, returns 0 if OK else returns error message */
- static short button_open(short x,short y,BUTTON *button,fg_pbox_t area,DIALOG_ITEM *d)
- {
- short cell_height,color;
- fg_box_t temp;
-
- if (button->name == NULL || (button->status & ~DIALOG_BITS) ||
- button->accelerator < KEY_MIN || button->accelerator > KEY_MAX)
- return M_INVALID_PARMS;
- if (is_active(*button) || is_gray(*button))
- {
- cell_height = gui_char_height + 6;
- if (gui_char_height + gui_char_height/2 > cell_height)
- cell_height = gui_char_height + gui_char_height/2;
- temp[FG_X1] = x+(gui_char_width*button->loc_x)/DIALOG_UNITS;
- temp[FG_Y1] = y+(gui_char_height*button->loc_y)/DIALOG_UNITS;
- if (is_gray(*button))
- {
- temp[FG_X2] = dialog_draw_gray_text(temp[FG_X1],temp[FG_Y1],button->name,area);
- color = COLOR_DIALOG_GRAY;
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- }
- else
- {
- temp[FG_X2] = dialog_draw_text(temp[FG_X1],temp[FG_Y1],button->name,area);
- color = COLOR_DIALOG_FOREGROUND;
- }
- temp[FG_X1] -= gui_char_width;
- temp[FG_X2] += gui_char_width;
- temp[FG_Y1] -= (cell_height-gui_char_height)/2;
- temp[FG_Y2] = temp[FG_Y1] + cell_height;
- fg_drawbox(color,FG_MODE_SET,~0,FG_LINE_SOLID,temp,area);
- fg_box_cpy(button->screen,temp);
- fg_box_cpy(d->focus,temp);
- }
- else
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- return 0;
- }
-
-
- /* ---------------- CHECKBOXES ---------------- */
-
- /* verify parameters and draw button, returns 0 if OK else returns error message */
- static short checkbox_open(short x,short y,BUTTON *button,fg_pbox_t area,DIALOG_ITEM *d)
- {
- if (button->name == NULL || (button->status & ~DIALOG_BITS) ||
- button->accelerator < KEY_MIN || button->accelerator > KEY_MAX)
- return M_INVALID_PARMS;
- if (is_gray(*button))
- {
- checkbox_draw_gray(x,y,button,area,d->focus);
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- }
- else if (is_active(*button))
- {
- checkbox_draw(x,y,button,area,d->focus);
- if (is_selected(*button))
- checkbox_mark(button);
- button->status |= DIALOG_OPENED;
- }
- else
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- return 0;
- }
-
-
- /* draw a checkbox and fill the hotspot info */
- static void checkbox_draw(short x,short y,BUTTON *b,fg_pbox_t clip,fg_pbox_t focus)
- {
- fg_box_t temp;
-
- temp[FG_X1] = x + (gui_char_width*b->loc_x)/DIALOG_UNITS;
- temp[FG_Y1] = y + (gui_char_height*b->loc_y)/DIALOG_UNITS;
- temp[FG_X2] = dialog_draw_text(temp[FG_X1],temp[FG_Y1],b->name,clip);
- temp[FG_X1] -= 2*gui_char_width;
- temp[FG_Y2] = temp[FG_Y1] + gui_char_height;
- fg_box_cpy(b->screen,temp);
- temp[FG_X2] = temp[FG_X1] + gui_char_width;
- temp[FG_Y1]++;
- temp[FG_Y2]--;
- fg_drawbox(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,temp,clip);
- fg_box_cpy(focus,temp);
- }
-
-
- /* draw a gray checkbox */
- static void checkbox_draw_gray(short x,short y,BUTTON *b,fg_pbox_t clip,fg_pbox_t focus)
- {
- fg_box_t temp;
-
- temp[FG_X1] = x + (gui_char_width*b->loc_x)/DIALOG_UNITS;
- temp[FG_Y1] = y + (gui_char_height*b->loc_y)/DIALOG_UNITS;
- temp[FG_X2] = dialog_draw_gray_text(temp[FG_X1],temp[FG_Y1],b->name,clip);
- temp[FG_X1] -= 2*gui_char_width;
- temp[FG_Y2] = temp[FG_Y1] + gui_char_height;
- fg_box_cpy(b->screen,temp);
- temp[FG_X2] = temp[FG_X1] + gui_char_width;
- temp[FG_Y1]++;
- temp[FG_Y2]--;
- fg_drawbox(COLOR_DIALOG_GRAY,FG_MODE_SET,~0,FG_LINE_SOLID,temp,clip);
- fg_box_cpy(focus,temp);
- }
-
-
- /* mark a check box by drawing an X and setting it selected */
- static void checkbox_mark(BUTTON *b)
- {
- fg_line_t line;
- fg_box_t clip;
-
- fg_msm_hidecursor();
- clip[FG_X1] = b->screen[FG_X1]+1;
- clip[FG_Y1] = b->screen[FG_Y1]+2;
- clip[FG_X2] = b->screen[FG_X1]+gui_char_width-1;
- clip[FG_Y2] = b->screen[FG_Y2]-2;
- line[FG_X1] = clip[FG_X1];
- line[FG_Y1] = clip[FG_Y1];
- line[FG_X2] = clip[FG_X2];
- line[FG_Y2] = clip[FG_Y2];
- fg_drawlineclip(COLOR_DIALOG_SELECTION,FG_MODE_SET,~0,FG_LINE_SOLID,line,clip);
- line[FG_X1] = clip[FG_X1];
- line[FG_Y1] = clip[FG_Y2];
- line[FG_X2] = clip[FG_X2];
- line[FG_Y2] = clip[FG_Y1];
- fg_drawlineclip(COLOR_DIALOG_SELECTION,FG_MODE_SET,~0,FG_LINE_SOLID,line,clip);
- b->status |= DIALOG_SELECTED;
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* unmark a check box by clearing the X and setting it not selected */
- static void checkbox_unmark(BUTTON *b)
- {
- fg_line_t line;
- fg_box_t clip;
-
- fg_msm_hidecursor();
- clip[FG_X1] = b->screen[FG_X1]+1;
- clip[FG_Y1] = b->screen[FG_Y1]+2;
- clip[FG_X2] = b->screen[FG_X1]+gui_char_width-1;
- clip[FG_Y2] = b->screen[FG_Y2]-2;
- line[FG_X1] = clip[FG_X1];
- line[FG_Y1] = clip[FG_Y1];
- line[FG_X2] = clip[FG_X2];
- line[FG_Y2] = clip[FG_Y2];
- fg_drawlineclip(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,line,clip);
- line[FG_X1] = clip[FG_X1];
- line[FG_Y1] = clip[FG_Y2];
- line[FG_X2] = clip[FG_X2];
- line[FG_Y2] = clip[FG_Y1];
- fg_drawlineclip(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,line,clip);
- b->status &= ~DIALOG_SELECTED;
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* ---------------- RADIOBUTTONS ---------------- */
-
- /* verify parameters and draw buttons, returns 0 if OK else returns error message */
- static short radiobutton_open(short x,short y,RADIOBUTTON *radio,fg_pbox_t area,DIALOG_ITEM *d)
- {
- short i;
- BUTTON *b;
- fg_box_t box;
-
- if (radio->number_of_buttons < 0 || radio->number_of_buttons > DIALOG_MAX_ITEMS || (radio->status & ~DIALOG_BITS))
- return M_INVALID_PARMS;
- for (i = 0 ; i < radio->number_of_buttons ; i++)
- {
- b = &(radio->buttons[i]);
- if (b->name == NULL || (b->status & ~DIALOG_BITS) ||
- b->accelerator < KEY_MIN || b->accelerator > KEY_MAX)
- return M_INVALID_PARMS;
- }
- if (is_active(*radio))
- {
- d->focus[FG_X1] = box[FG_X1] = -999;
- for (i = 0 ; i < radio->number_of_buttons ; i++)
- {
- b = &(radio->buttons[i]);
- if (is_gray(*b))
- checkbox_draw_gray(x,y,b,area,box);
- if (is_active(*b))
- {
- checkbox_draw(x,y,b,area,box);
- if (is_selected(*b))
- {
- radiobutton_mark(b,NULL);
- fg_box_cpy(d->focus,box);
- }
- }
- }
- if (d->focus[FG_X1] == -999) /* nothing selected, focus on last or skip */
- if (box[FG_X1] == -999)
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- else
- fg_box_cpy(d->focus,box);
- radio->status |= DIALOG_OPENED;
- radio->dialog = d;
- }
- else
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- return 0;
- }
-
-
- /* mark a radio button as on and set it as selected, also set focus */
- static void radiobutton_mark(BUTTON *b,DIALOG_ITEM *d)
- {
- fg_box_t box;
-
- fg_msm_hidecursor();
- box[FG_X1] = b->screen[FG_X1];
- box[FG_Y1] = b->screen[FG_Y1] + 1;
- box[FG_X2] = box[FG_X1] + gui_char_width;
- box[FG_Y2] = b->screen[FG_Y2] - 1;
- if (d != NULL)
- {
- if (d->dialog_state & DIALOG_FOCUS_HERE)
- {
- dialog_focus_draw(d,FOCUS_CLEAR);
- fg_box_cpy(d->focus,box);
- dialog_focus_draw(d,FOCUS_SET);
- }
- else
- fg_box_cpy(d->focus,box);
- }
- box[FG_X1] += 2;
- box[FG_Y1] += 2;
- box[FG_X2] -= 2;
- box[FG_Y2] -= 2;
- fg_boxclip(fg.displaybox,box,box);
- fg_fillbox(COLOR_DIALOG_SELECTION,FG_MODE_SET,~0,box);
- b->status |= DIALOG_SELECTED;
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* unmark a radio button as off and set it as not selected */
- static void radiobutton_unmark(BUTTON *b)
- {
- fg_box_t box;
-
- fg_msm_hidecursor();
- box[FG_X1] = b->screen[FG_X1]+2;
- box[FG_Y1] = b->screen[FG_Y1]+3;
- box[FG_X2] = b->screen[FG_X1]+gui_char_width-2;
- box[FG_Y2] = b->screen[FG_Y2]-3;
- fg_boxclip(fg.displaybox,box,box);
- fg_fillbox(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,box);
- b->status &= ~DIALOG_SELECTED;
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* unmark any radio button which may be on and deselect it
- * enter with pointer to first button
- * returns a pointer to the unmarked button or NULL if none */
- static BUTTON *radiobutton_unmark_all(BUTTON *first,short number_of_buttons)
- {
- BUTTON *b,*b2;
- short i;
-
- for (i = 0, b = first, b2 = NULL ; i < number_of_buttons ; i++, b++)
- if (is_selected(*b))
- {
- radiobutton_unmark(b);
- b2 = b;
- }
- return b2;
- }
-
-
- /* return the previous button in a radiobutton sequence */
- static BUTTON *radiobutton_previous(BUTTON *first,short number_of_buttons)
- {
- short current,mark;
-
- for (current = 0 ; current < number_of_buttons ; current++)
- if (is_selected(*(first+current))) /* find current */
- break;
- mark = current;
- do /* find previous */
- {
- if (--current < 0)
- current = number_of_buttons-1;
- if (current == mark)
- break;
- } while (is_inactive(*(first+current)));
- return first+current;
- }
-
-
- /* return the next button in a radiobutton sequence */
- static BUTTON *radiobutton_next(BUTTON *first,short number_of_buttons)
- {
- short current,mark;
-
- for (current = 0 ; current < number_of_buttons ; current++)
- if (is_selected(*(first+current))) /* find current */
- break;
- mark = current;
- do /* find next */
- {
- if (++current >= number_of_buttons)
- current = 0;
- if (current == mark)
- break;
- } while (is_inactive(*(first+current)));
- return first+current;
- }
-
-
- /* ---------------- LISTBOXES ---------------- */
-
- /* verify parameters and open a listbox */
- static short listbox_open(short x,short y,LISTBOX *list,fg_pbox_t area,DIALOG_ITEM *d)
- {
- fg_box_t temp;
-
- if (list->width < DIALOG_UNITS || list->height < DIALOG_UNITS ||
- list->first_item == NULL || list->next_item == NULL ||
- (list->status & ~DIALOG_BITS))
- return M_INVALID_PARMS;
- if (is_active(*list))
- {
- list->status &= ~DIALOG_COMPLETED;
- temp[FG_X1] = x+(gui_char_width*list->loc_x)/DIALOG_UNITS;
- temp[FG_Y1] = y+(gui_char_height*list->loc_y)/DIALOG_UNITS;
- temp[FG_X2] = temp[FG_X1]+gui_char_width*(list->width/DIALOG_UNITS+2)+5;
- temp[FG_Y2] = temp[FG_Y1]+gui_char_height*(list->height/DIALOG_UNITS)+1;
- fg_box_cpy(list->screen,temp);
- fg_box_cpy(d->focus,temp);
- fg_drawbox(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,temp,area);
- temp[FG_X2] = temp[FG_X1] + gui_char_width + 1;
- list->marker[FG_X1] = temp[FG_X1] + 1;
- list->marker[FG_Y1] = temp[FG_Y1] + 1;
- list->marker[FG_X2] = temp[FG_X2] - 1;
- list->marker[FG_Y2] = temp[FG_Y2] - 1;
- fg_boxclip(fg.displaybox,list->marker,list->marker);
- list->listbox[FG_X1] = temp[FG_X2] + 2;
- list->listbox[FG_Y1] = temp[FG_Y1] + 1;
- list->listbox[FG_Y2] = temp[FG_Y2] - 1;
- fg_drawbox(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,temp,area);
- temp[FG_X2] = list->screen[FG_X2];
- temp[FG_X1] = temp[FG_X2] - gui_char_width - 1;
- list->listbox[FG_X2] = temp[FG_X1] - 2;
- fg_boxclip(fg.displaybox,list->listbox,list->listbox);
- fg_drawbox(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,temp,area);
- temp[FG_Y2] = temp[FG_Y1] + (temp[FG_Y2] - temp[FG_Y1])/2;
- fg_drawbox(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,temp,area);
- fg_putc(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_ROT0,temp[FG_X1]+1,list->screen[FG_Y2]-gui_char_height-1,LIST_UPARROW,area);
- fg_putc(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_ROT0,temp[FG_X1]+1,list->screen[FG_Y1]+1,LIST_DOWNARROW,area);
- list->up[FG_X1] = list->down[FG_X1] = temp[FG_X1];
- list->up[FG_X2] = list->down[FG_X2] = temp[FG_X2];
- list->up[FG_Y1] = temp[FG_Y2] + 1;
- list->up[FG_Y2] = list->screen[FG_Y2];
- list->down[FG_Y1] = list->screen[FG_Y1];
- list->down[FG_Y2] = temp[FG_Y2];
- list->first_page = NULL;
- list->status |= DIALOG_OPENED;
- if (!listbox_initialize(list))
- return M_NULL_ERROR;
- }
- else
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- return 0;
- }
-
-
- /* free allocated listbox pages and mark as unopened */
- static void listbox_close(LISTBOX *list)
- {
- if (list->status & DIALOG_OPENED)
- {
- listbox_free(list);
- list->status &= ~(DIALOG_OPENED | DIALOG_COMPLETED);
- }
- }
-
-
- /* free the pages allocated to the listbox */
- static void listbox_free(LISTBOX *list)
- {
- LISTBOX_PAGE *lp,*lp2;
-
- lp = list->first_page;
- while (lp != NULL)
- {
- lp2 = lp->next_page;
- free(lp);
- lp = lp2;
- }
- list->first_page = NULL;
- }
-
-
- /* erase the current list box and redraw using list->current_page and list->page_offset as the top of the list */
- static void listbox_draw_contents(LISTBOX *list)
- {
- short x,y,box_height,string_size,page_offset;
- char *p;
- LISTBOX_PAGE *lp;
-
- fg_msm_hidecursor();
- fg_fillbox(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,list->listbox); /* erase old list */
- string_size = list->width/DIALOG_UNITS + 1; /* initialize variables */
- box_height = list->height/DIALOG_UNITS;
- lp = list->current_page;
- x = list->listbox[FG_X1];
- y = list->listbox[FG_Y2] - gui_char_height;
- page_offset = list->page_offset;
- p = lp->listbox_items + string_size * page_offset;
- while (box_height)
- { /* for each line in the box */
- if (page_offset >= lp->number_of_items)
- { /* if end of page, go to next page */
- if (lp->next_page == NULL)
- { /* next page not found, try to load it */
- if (!listbox_allocate_page(list,LISTBOX_SUCCEEDING_PAGES))
- { /* fill next page */
- fg_msm_showcursor();
- fg_flush();
- return;
- }
- if (list->status & DIALOG_COMPLETED)
- break; /* no more pages */
- }
- lp = lp->next_page; /* adjust page pointers to next page */
- p = lp->listbox_items;
- page_offset = 0;
- }
- fg_puts(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_ROT0,x,y,p,list->listbox);
- box_height--; /* adjust variables */
- page_offset++;
- y -= gui_char_height;
- p += string_size;
- }
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* allocate a new listbox page and fill it, returns pointer to page if OK or NULL if failed */
- static short listbox_allocate_page(LISTBOX *list,short type)
- {
- short i,string_size;
- char *p;
- LISTBOX_PAGE *lp,*lp2;
- MESSAGE error;
-
- if (type == LISTBOX_SUCCEEDING_PAGES && (list->status & DIALOG_COMPLETED))
- return 1; /* list finished, no allocation needed */
- string_size = list->width/DIALOG_UNITS + 1;
- if ((lp = (LISTBOX_PAGE *) malloc(sizeof(LISTBOX_PAGE)+LISTBOX_MEM_PAGE_SIZE*string_size)) == NULL)
- { /* allocate page */
- error.id = gui_errno = M_NOMEM;
- error.data.ptr_data = listbox_allocate_page;
- message_send(&error);
- return 0;
- }
- lp->listbox_items = (char *) lp + sizeof(LISTBOX_PAGE); /* initialize page */
- lp->number_of_items = 0;
- if (type == LISTBOX_FIRST_PAGE)
- { /* first page is special */
- lp->previous_page = NULL;
- lp->next_page = NULL;
- if ((*(list->first_item))(lp->listbox_items)) /* fill first page */
- {
- for (i=lp->number_of_items=1, p=lp->listbox_items+string_size ; i < LISTBOX_MEM_PAGE_SIZE ; i++, p+=string_size)
- { /* continue filling */
- if ((*(list->next_item))(p))
- lp->number_of_items++;
- else
- {
- list->status |= DIALOG_COMPLETED; /* list complete in this page */
- break;
- }
- }
- }
- else
- list->status |= DIALOG_COMPLETED; /* empty list */
- list->first_page = list->current_page = lp; /* preset list pointers and counters */
- list->page_offset = list->screen_offset = 0;
- }
- else if (type == LISTBOX_SUCCEEDING_PAGES)
- {
- for (lp2 = list->current_page ; lp2->next_page != NULL ; lp2 = lp2->next_page)
- ; /* find end of list */
- lp2->next_page = lp; /* thread page on to list */
- lp->next_page = NULL;
- lp->previous_page = lp2;
- for (i=0, p=lp->listbox_items ; i < LISTBOX_MEM_PAGE_SIZE ; i++, p+=string_size)
- { /* fill page */
- if ((*(list->next_item))(p))
- lp->number_of_items++;
- else
- {
- list->status |= DIALOG_COMPLETED; /* list complete in this page */
- if (lp->number_of_items == 0)
- { /* nothing to put in this page */
- lp2->next_page = NULL;
- free(lp);
- }
- break;
- }
- }
- }
- else /* illegal type specifier */
- {
- free(lp);
- error.id = gui_errno = M_INVALID_PARMS;
- error.data.ptr_data = listbox_allocate_page;
- message_send(&error);
- return 0;
- }
- return 1;
- }
-
-
- /* mark active selection in list box */
- static void listbox_mark(LISTBOX *list)
- {
- fg_msm_hidecursor();
- fg_fillbox(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,list->marker); /* erase old marker */
- if (list->first_page->next_page != NULL || list->first_page->number_of_items != 0)
- fg_putc(COLOR_DIALOG_SELECTION,FG_MODE_SET,~0,FG_ROT0,list->marker[FG_X1],list->marker[FG_Y2]-gui_char_height*(list->screen_offset+1),LIST_RIGHTARROW,list->marker);
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* scroll the listbox by the number of lines, returns 1 if OK or 0 if failed */
- static short listbox_scroll(LISTBOX *list,short number_of_lines)
- {
- short height,ret;
- LISTBOX_PAGE *lp;
- short page_offset,height_count;
-
- ret = 1;
- height = list->height/DIALOG_UNITS;
- if (number_of_lines < 0) /* scroll up */
- {
- if (list->screen_offset + number_of_lines >= 0)
- list->screen_offset += number_of_lines; /* just move marker */
- else
- { /* redraw page */
- while (number_of_lines)
- {
- if (list->page_offset == 0)
- { /* get previous page */
- if (list->current_page->previous_page == NULL)
- { /* no more previous pages */
- list->screen_offset += number_of_lines;
- if (list->screen_offset < 0)
- list->screen_offset = 0;
- break;
- }
- else
- { /* point to previous page */
- list->current_page = list->current_page->previous_page;
- list->page_offset = list->current_page->number_of_items;
- }
- }
- list->page_offset--;
- number_of_lines++;
- }
- listbox_draw_contents(list);
- }
- listbox_mark(list);
- }
- else if (number_of_lines > 0) /* scroll down */
- {
- for (lp=list->current_page, page_offset=list->page_offset, height_count=0 ; height_count < height-1 ; height_count++)
- if (++page_offset >= lp->number_of_items) /* get pointer at bottom of screen */
- {
- if ((lp = lp->next_page) == NULL) break;
- page_offset = 0;
- }
- if (lp == NULL || list->screen_offset+number_of_lines < height)
- { /* move within current screen or partially filled screen */
- list->screen_offset += number_of_lines;
- if (list->screen_offset > height_count)
- list->screen_offset = height_count;
- }
- else
- { /* redraw page */
- while (number_of_lines)
- {
- if (++page_offset >= lp->number_of_items)
- { /* need more pages */
- if (lp->next_page == NULL)
- {
- ret = listbox_allocate_page(list,LISTBOX_SUCCEEDING_PAGES);
- if (ret == 0 || lp->next_page == NULL)
- { /* nothing actually added */
- list->status |= DIALOG_COMPLETED;
- break;
- }
- }
- lp = lp->next_page;
- page_offset = 0;
- }
- list->page_offset++;
- if (list->page_offset >= list->current_page->number_of_items)
- { /* get next page */
- if (list->current_page->next_page == NULL)
- { /* this code should not be reached but is included as a safety plug */
- list->page_offset--;
- break;
- }
- list->current_page = list->current_page->next_page;
- list->page_offset = 0;
- }
- number_of_lines--;
- }
- if (list->screen_offset + number_of_lines >= height)
- { /* still want more? move to bottom of page */
- list->screen_offset = height-1;
- }
- listbox_draw_contents(list);
- }
- listbox_mark(list);
- }
- return ret;
- }
-
-
- /* return current data for listbox at offset from top, or NULL if none */
- static char *listbox_current_data(LISTBOX *list,short offset)
- {
- LISTBOX_PAGE *lp;
- short page_offset;
-
- for (lp=list->current_page, page_offset=list->page_offset ; offset > 0 ; offset--)
- {
- page_offset++;
- if (page_offset >= lp->number_of_items)
- { /* get next page */
- if (lp->next_page == NULL)
- return NULL;
- lp = lp->next_page;
- page_offset = 0;
- }
- }
- return lp->listbox_items + page_offset * (list->width/DIALOG_UNITS + 1);
- }
-
-
- /* ---------------- EDITBOXES ---------------- */
-
- /* verify parameters and open an editbox */
- static short editbox_open(short x,short y,EDITBOX *edit,fg_pbox_t area,DIALOG_ITEM *d)
- {
- fg_box_t temp;
-
- if (edit->edit_width < 1 || edit->edit_width < edit->screen_width/DIALOG_UNITS ||
- edit->edit_string == NULL || (edit->status & ~DIALOG_BITS))
- return M_INVALID_PARMS;
- if (is_active(*edit))
- {
- temp[FG_X1] = x+(gui_char_width*edit->loc_x)/DIALOG_UNITS;
- temp[FG_Y1] = y+(gui_char_height*edit->loc_y)/DIALOG_UNITS;
- temp[FG_X2] = temp[FG_X1]+gui_char_width*(edit->screen_width/DIALOG_UNITS)+4;
- temp[FG_Y2] = temp[FG_Y1]+gui_char_height+2;
- fg_boxclip(fg.displaybox,temp,temp);
- fg_box_cpy(edit->screen,temp);
- fg_box_cpy(d->focus,temp);
- fg_drawbox(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,temp,area);
- edit->status |= DIALOG_OPENED;
- editbox_initialize(edit);
- }
- else
- d->dialog_state |= DIALOG_FOCUS_SKIP;
- return 0;
- }
-
-
- /* strip trailing whitespace from string and mark as unopened */
- static void editbox_close(EDITBOX *edit)
- {
- short i;
-
- if (edit->status & DIALOG_OPENED)
- {
- edit->status &= ~DIALOG_OPENED;
- for (i = edit->edit_width-1 ; i >= 0 ; i--)
- if (edit->edit_string[i] == ' ')
- edit->edit_string[i] = 0;
- else
- break;
- }
- }
-
-
- /* draw the editbox contents starting from scroll_offset and place cursor */
- static void editbox_draw(EDITBOX *edit)
- {
- fg_box_t temp;
- short c,screen_width;
- char *p;
-
- p = edit->edit_string + edit->scroll_offset;
- screen_width = edit->screen_width/DIALOG_UNITS;
- fg_msm_hidecursor();
- fg_box_cpy(temp,edit->screen);
- temp[FG_X1]++;
- temp[FG_Y1]++;
- temp[FG_X2]--;
- temp[FG_Y2]--;
- fg_fillbox(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,temp);
- c = p[screen_width];
- p[screen_width] = 0;
- fg_puts(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_ROT0,temp[FG_X1],temp[FG_Y1],p,edit->screen);
- p[screen_width] = c;
- editbox_cursor(edit);
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* move the editbox cursor */
- static void editbox_cursor(EDITBOX *edit)
- {
- short x,y;
-
- x = edit->screen[FG_X1] + 1;
- y = edit->screen[FG_Y1] + 1;
- fg_msm_hidecursor();
- fg_putc(COLOR_DIALOG_BACKGROUND,FG_MODE_SET,~0,FG_ROT0,x+(edit->curpos-edit->scroll_offset)*gui_char_width,y,(edit->curtype)?(EDITBOX_CURSOR_INSERT):(EDITBOX_CURSOR_OVERWRITE),edit->screen);
- fg_putc(COLOR_DIALOG_FOREGROUND,FG_MODE_SET,~0,FG_ROT0,x+(edit->curpos-edit->scroll_offset)*gui_char_width,y,edit->edit_string[edit->curpos],edit->screen);
- fg_putc(COLOR_DIALOG_SELECTION,FG_MODE_SET,~0,FG_ROT0,x+(edit->xpos-edit->scroll_offset)*gui_char_width,y,(edit->insert)?(EDITBOX_CURSOR_INSERT):(EDITBOX_CURSOR_OVERWRITE),edit->screen);
- edit->curpos = edit->xpos;
- edit->curtype = edit->insert;
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /* using key, edit the line in the editbox.
- * If any edit changes were made return 2, if the key was consumed return 1,
- * else return 0 */
- static short editbox_edit(EDITBOX *edit,short key)
- {
- short ret,width,i,x,scrolled,len;
- char *str;
-
- ret = scrolled = 0; /* preset variables */
- x = edit->xpos;
- width = edit->edit_width;
- str = edit->edit_string;
- switch (key)
- {
- case LEFTARROW: /* move left */
- if (x > 0)
- x--;
- ret = 1;
- break;
- case RIGHTARROW: /* move right */
- if (str[x] == 0)
- {
- str[x+1] = 0;
- str[x] = ' ';
- }
- if (x < width-1)
- x++;
- ret = 1;
- break;
- case EDITBOX_HOME: /* move to beginning */
- x = 0;
- ret = 1;
- break;
- case EDITBOX_END: /* move to end */
- for (x = strlen(str) ; x > 0 ; x--)
- if (str[x-1] != ' ')
- break;
- if (x >= width)
- x--;
- ret = 1;
- break;
- case INS: /* toggle insert mode */
- edit->insert ^= 1;
- ret = 1;
- break;
- case DELETE: /* delete at cursor */
- for (i = x ; i < strlen(str) ; i++)
- str[i] = str[i+1];
- ret = 2;
- break;
- case EDITBOX_DELETE_EOL: /* delete to end of line */
- str[x] = 0;
- ret = 2;
- break;
- case BKSP: /* delete to right */
- if (x == 0)
- break;
- for (i = --x ; i < strlen(str) ; i++)
- str[i] = str[i+1];
- ret = 2;
- break;
- default: /* if printable, print it */
- if (!isprint_ibm(key))
- break;
- if (edit->insert)
- {
- len = strlen(str);
- if (len < width)
- str[len+1] = 0;
- else
- len--;
- for (i = len ; i > x ; i--)
- str[i] = str[i-1];
- }
- else
- if (str[x] == 0)
- str[x+1] = 0;
- str[x] = key;
- if (x < width-1)
- x++;
- ret = 2;
- break;
- }
- edit->xpos = x;
- if (x < edit->scroll_offset)
- {
- edit->scroll_offset = x;
- scrolled = 1;
- }
- if (x >= edit->scroll_offset+edit->screen_width/DIALOG_UNITS)
- {
- edit->scroll_offset = x - edit->screen_width/DIALOG_UNITS + 1;
- scrolled = 1;
- }
- if (ret == 2 || scrolled == 1) /* rewrite editbox if changed or scrolled */
- editbox_draw(edit);
- if (ret == 1 && scrolled == 0) /* just move cursor if changed */
- editbox_cursor(edit);
- return ret;
- }